package com.ia2014.tp.portal2.ejb;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.ejb.EJB;
import javax.ejb.Stateful;
import javax.ejb.StatefulTimeout;
import javax.enterprise.context.SessionScoped;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceException;

import org.apache.log4j.Logger;

import webservices.client.InformarVentaLogistica;

import com.ia2014.tp.portal2.entities.Venta;
import com.ia2014.tp.portal2.entities.ItemVenta;
import com.ia2014.tp.portal2.entities.Articulo;
import com.ia2014.tp.portal2.entities.Usuario;
import com.ia2014.tp.portal2.enums.EstadoVentaEnum;
import com.ia2014.tp.portal2.integration.converters.entities.Response;
import com.ia2014.tp.portal2.log.*;
import com.ia2014.tp.portal2.utils.Helper;
import com.ia2014.tp.portal2.vo.ItemVentaVO;
import com.ia2014.tp.portal2.vo.UsuarioVO;


/**
 * Session Bean implementation class AdministradorCarritosBean
 */
@Stateful
@SessionScoped
@StatefulTimeout(value=2, unit=TimeUnit.HOURS)
public class AdministradorCarritosBean implements AdministradorCarritos {

	
	private static Logger logger = Logger.getLogger(AdministradorCarritosBean.class);
	
	@PersistenceContext(unitName = "DAO")
    private EntityManager em;
	
	@EJB
	private AdministradorUsuarios administradorUsuarios;
	
	@EJB
	private AdministradorConfig administradorConfig;
	
	
	private Usuario usuario;
	
	public Usuario getUsuario() {
		return usuario;
	}

	public void setUsuario(Usuario usuario) {
		this.usuario = usuario;
	}

	List<ItemVentaVO> items;

	public AdministradorCarritosBean(){
		super();
		this.items = new ArrayList<ItemVentaVO>();
	}
	
	@Override
	public boolean login(UsuarioVO usuarioVO) {
		
		try{
			
			usuarioVO = administradorUsuarios.autenticarUsuario(usuarioVO);
		
			if (usuarioVO != null) {
			
				usuario = new Usuario();
				usuario.setVO(usuarioVO);
			
				items = new ArrayList<ItemVentaVO>();
			
				//Actauliza la configuracion
				administradorConfig.actualizarConfiguracion();
				
			return true;
		}
		else
			return false;
		}
		
		catch(Exception e){
			logger.error("Error al tratar de iniciar sesion con el usuario " + usuarioVO.getUserLogin());
			logger.error(e.toString());
			logger.debug("Stacktrace", e);
			
			return false;
		}
	}

	@Override
	public void agregarItem(ItemVentaVO item) {
		
		try{
			
			//Actauliza la configuracion
			administradorConfig.actualizarConfiguracion();
			
			//items.add(item);
		
			//Mensaje al Monitor
			LogsLogisticaMonitoreo.logMessage("El usuario - " + this.usuario.getUserLogin() + " - del Portal Web 2 ha agregado el articulo - " + item.getArticulo().getNombre() + " - a su Carrito");
		
		}
		catch(Exception e){
			logger.error("Error al tratar de agregar el articulo " + item.getArticulo().getId() + " a la Venta del Usuario " + usuario.getUserLogin() );
			logger.error(e.toString());
			logger.debug("Stacktrace", e);
		}
	}

	@Override
	public void eliminarItem(Integer idArticulo){
		
		try{
			//Actauliza la configuracion
			administradorConfig.actualizarConfiguracion();
			
			ItemVentaVO item = null;
			Iterator<ItemVentaVO> it = items.iterator();
		
			boolean found = false;
		
			while (it.hasNext() && !found) {
		
				item = (ItemVentaVO) it.next();
			
				found = (item.getArticulo().getId().intValue() == idArticulo.intValue());
				
			}
			if (found) {
				it.remove();
				//Mensaje al Monitor
				LogsLogisticaMonitoreo.logMessage("El usuario - " + this.usuario.getUserLogin() + " - del Portal Web 2 ha quitado el articulo - " + item.getArticulo().getNombre() + " - de su Carrito");
			}	
		}
		catch(Exception e){
			logger.error("Error al tratar de eliminar el Articulo con ID" + String.valueOf(idArticulo) + " de la Venta del Usuario " + usuario.getUserLogin() );
			logger.error(e.toString());
			logger.debug("Stacktrace", e);
		}
	}
	
	@Override
	public ItemVentaVO buscarItem(Integer idArticulo) {
		
		try {
		ItemVentaVO item = null;
		
		boolean found = false;
		
		Iterator<ItemVentaVO> it = items.iterator();
		
		while (it.hasNext() && !found) {
			item = (ItemVentaVO) it.next();
			
			found = (item.getArticulo().getId().intValue() == idArticulo.intValue());	
		}
		
		if(!found)return null;
		else return item;
		
		}
		catch(Exception e){
			logger.error("Error al tratar de buscar el Articulo con ID " + String.valueOf(idArticulo) + " entre los articulos de la Venta del Usuario " + usuario.getUserLogin() );
			logger.error(e.toString());
			logger.debug("Stacktrace", e);
			
			return null;
		}
	}
	
	@Override
	public void actualizarCantidadItem(Integer idArticulo, int cant) {
		try{
			//Actauliza la configuracion
			administradorConfig.actualizarConfiguracion();
			
			ItemVentaVO item = null;
			int i = 0;
			for (Iterator<ItemVentaVO> it = items.iterator(); it.hasNext(); i++) {
	    	
				item = (ItemVentaVO)it.next();
	        
				if(item.getArticulo().getId().intValue() == idArticulo.intValue()){
					items.get(i).setCantidad(item.getCantidad() + cant);
	            
					//Mensaje al Monitor
					LogsLogisticaMonitoreo.logMessage("El usuario - " + this.usuario.getUserLogin() + " - del Portal Web 2 ha aumentado en " + cant +" la cantidad del articulo - " + item.getArticulo().getNombre() + " - de su Carrito");
	        }
	     }
		}
		catch(Exception e){
			logger.error("Error al tratar de actualizar la cantidad del Articulo con ID " + String.valueOf(idArticulo)  + " de la Venta del Usuario " + usuario.getUserLogin() );
			logger.error(e.toString());
			logger.debug("Stacktrace", e);
		}
	}

	@Override
	public List<ItemVentaVO> getListaItems() {
		return items;
	}

	@Override
	public void eliminarVenta() {
		this.items = null;
		
	}
		
	private void setItemsVenta(Venta venta, List<ItemVentaVO> listVO) {
		
		try {
		for (ItemVentaVO itemVO : listVO) {
			
			ItemVenta item = new ItemVenta();
			
			item.setVO(itemVO);

			Integer idArticulo = itemVO.getArticulo().getId();
			
			Articulo articulo = em.find(Articulo.class, idArticulo);
			
			item.setArticulo(articulo);

			item.setVenta(venta);
			
			venta.addItemVenta(item);
		}
		}
		catch(Exception e){
			logger.error("Error al tratar de agregar los items al Entity Venta del Usuario " + usuario.getUserLogin() );
			logger.error(e.toString());
			logger.debug("Stacktrace", e);
		}
	}
	
	@Override
	public void confirmarVenta(){
		
		Venta venta = new Venta();
		
		try
		{
			//Actauliza la configuracion
			administradorConfig.actualizarConfiguracion();
			
			//persiste la venta
			
			logger.info("Confirmando Venta.\nUsuario: " + usuario.getUserLogin());
			
			usuario.setVO(administradorUsuarios.autenticarUsuario(usuario.getVO()));
			
			this.em.merge(usuario);
			
			//System.out.println("X2: " + usuario.getCoordenadaX());
			
			//System.out.println("Y2: " + usuario.getCoordenadaY());
			
			venta.setEstado(EstadoVentaEnum.A_CONFIRMAR.toString());
			
			venta.setUsuario(usuario);
			
			venta.setFecha(new Date());
		
			setItemsVenta(venta, items);
			
			venta.setEstadoItems(EstadoVentaEnum.A_CONFIRMAR.toString());
			
			
			//System.out.println("X3: " + venta.getUsuario().getCoordenadaX());
			
			//System.out.println("Y3: " + venta.getUsuario().getCoordenadaY());
			
			em.persist(venta);
			
			//informa la venta al modulo Logistica Monitoreo
			InformarVentaLogistica informarVentaLogistica = new InformarVentaLogistica();
			
			Response resultado = informarVentaLogistica.enviarVentaALogistica(venta.getVO());
			
			//Se actualiza el estado de la venta
			if("OK".equalsIgnoreCase(resultado.getEstado())){
				logger.info("Confirmacion OK recepcion Venta del usuario - " + this.usuario.getUserLogin());
				//System.out.println("Confirmacion OK recepcion Venta por el modulo Logistica Monitoreo");
				
				venta.setEstado(EstadoVentaEnum.CONFIRMADA.toString());
				
				venta.setEstadoItems(EstadoVentaEnum.CONFIRMADA.toString());
				
			}
			else{
				//logger.info("ERROR recepcion Venta por el modulo Logistica Monitoreo");
				logger.error("ERROR recepcion Venta del usuario - " + this.usuario.getUserLogin());
				
				//System.out.println("ERROR recepcion Venta por el modulo Logistica Monitoreo");
				
				venta.setEstado(EstadoVentaEnum.NO_EXITOSO.toString());
				venta.setEstadoItems(EstadoVentaEnum.NO_EXITOSO.toString());
				
				
			}
			
			//Actualiza el estado de la venta
			em.merge(venta);
			
			//Mensaje al Monitor
			if("OK".equalsIgnoreCase(resultado.getEstado())){
				//Finalizo correctamente la confirmacion de la venta
				LogsLogisticaMonitoreo.logMessage("El usuario - " + this.usuario.getUserLogin() + " - del Portal Web 2 ha cerrado su Venta Exitosamente");
			}
			else{
				//Errror al recepcionarl la venta por parte del Monitor
				LogsLogisticaMonitoreo.logMessage("El usuario - " + this.usuario.getUserLogin() + 
						" - del Portal Web 2 ha cerrado su Venta con Errores. Estado: " + resultado.getEstado() + ". Mensaje de Error: " + resultado.getMensaje());
			}
		
		}
		catch(PersistenceException pe){

			logger.error("Error al persistir la venta");
			logger.error(pe.toString());
			logger.debug("Stacktrace", pe);
			
			//Mensaje al Monitor
			LogsLogisticaMonitoreo.logMessage("Error al persistir la venta");
			LogsLogisticaMonitoreo.logMessage("El usuario - " + this.usuario.getUserLogin() + " - del Portal Web 2 ha cerrado su Venta con Errores");
		}
		catch(Exception ex){
			
			//Rollback. 
			venta.setEstado(EstadoVentaEnum.NO_EXITOSO.toString());
			venta.setEstadoItems(EstadoVentaEnum.NO_EXITOSO.toString());
			
			logger.error("Error externo al confirmar la venta");
			logger.error(ex.toString());
			logger.debug("Stacktrace", ex);
			
			//Mensaje al Monitor
			LogsLogisticaMonitoreo.logMessage("El usuario - " + this.usuario.getUserLogin() + " - del Portal Web 2 ha cerrado su Venta con Errores");
		}
				
		this.items.clear();
		
	}

	@Override
	public List<ItemVentaVO> getItems() {
		return items;
	}

	@Override
	public void setItems(List<ItemVentaVO> items) {
		this.items = items;
	}
	
	
}
